﻿@page "/Implants"
@using HardHatCore.ApiModels.Plugin_BaseClasses;
@using HardHatCore.HardHatC2Client.Components;
@using HardHatCore.HardHatC2Client.Plugin_BaseClasses;
@using HardHatCore.HardHatC2Client.Components.ImplantCreation;
@using RestSharp
@using HardHatCore.HardHatC2Client.Services
@using System.Collections.ObjectModel
@using System.Linq
@using System.Diagnostics;
@using Blazored.LocalStorage
@using RestSharp.Authenticators;
@inject RestClient restClientDefault
@inject IToastService toastDefault
@inject NavigationManager navigationManagerDefault
@inject IDialogService dialogServiceDefault

<CascadingAuthenticationState>
    <AuthorizeView Roles="Operator,TeamLead">
        <Authorized>
            <br>
        <h3>Implants</h3>
            <MudTabs>
                <MudTabPanel Text="Table View / Creation">
            <br>
            <div oncontextmenu="return false;" @onclick="HandleClick" @onmouseup="HandleMouseUp">
            <div class="container-fluid d-flex flex-grow-1" style="height:500px; overflow-y:scroll">
           <style>
            .selected 
            {
                background-color: #1E88E5 !important;
            }
            .selected > td 
            {
                color: white !important;
            }   
            .selected > td .mud-input 
            {
                color: white !important;
            }

            .dialog-blur-class {
                backdrop-filter: blur(10px);
            }
            </style>
                           
                @if (HideOfflineImplants)
                {
                    ImplantDisplayList = ImplantList.Where(x => x.Status == "Active").ToList();
                }
                else
                {
                    ImplantDisplayList = ImplantList.ToList();
                }
                            
                <MudDialog IsVisible="@OpenDialog">
                    <DialogContent>
                                <MudCheckBox Label="Implant Number" Checked="@ColumnVisibility["Number"]" CheckedChanged="@EventCallback.Factory.Create(this, (bool isChecked) => ToggleColumnVisibility("Number"))"></MudCheckBox>
                        <MudCheckBox Label="Status" Checked="@ColumnVisibility["Status"]" CheckedChanged="@EventCallback.Factory.Create(this, (bool isChecked) => @ToggleColumnVisibility("Status"))"></MudCheckBox>
                        <MudCheckBox Label="External Address" Checked="@ColumnVisibility["ExternalAddress"]" CheckedChanged="@EventCallback.Factory.Create(this, (bool isChecked) => @ToggleColumnVisibility("ExternalAddress"))"></MudCheckBox>
                                <MudCheckBox Label="Manager" Checked="@ColumnVisibility["ManagerName"]" CheckedChanged="@EventCallback.Factory.Create(this, (bool isChecked) => @ToggleColumnVisibility("ManagerName"))"></MudCheckBox>
                                <MudCheckBox Label="Connection Type" Checked="@ColumnVisibility["ConnectionType"]" CheckedChanged="@EventCallback.Factory.Create(this, (bool isChecked) => @ToggleColumnVisibility("ConnectionType"))"></MudCheckBox>
                                <MudCheckBox Label="Address" Checked="@ColumnVisibility["Address"]" CheckedChanged="@EventCallback.Factory.Create(this, (bool isChecked) => @ToggleColumnVisibility("Address"))"></MudCheckBox>
                                <MudCheckBox Label="Hostname" Checked="@ColumnVisibility["Hostname"]" CheckedChanged="@EventCallback.Factory.Create(this, (bool isChecked) => @ToggleColumnVisibility("Hostname"))"></MudCheckBox>
                        <MudCheckBox Label="Username" Checked="@ColumnVisibility["Username"]" CheckedChanged="@EventCallback.Factory.Create(this, (bool isChecked) => @ToggleColumnVisibility("Username"))"></MudCheckBox>
                        <MudCheckBox Label="Note" Checked="@ColumnVisibility["Note"]" CheckedChanged="@EventCallback.Factory.Create(this, (bool isChecked) => @ToggleColumnVisibility("Note"))"></MudCheckBox>
                                <MudCheckBox Label="Process Name" Checked="@ColumnVisibility["ProcessName"]" CheckedChanged="@EventCallback.Factory.Create(this, (bool isChecked) => @ToggleColumnVisibility("ProcessName"))"></MudCheckBox>
                                <MudCheckBox Label="Process Id" Checked="@ColumnVisibility["ProcessId"]" CheckedChanged="@EventCallback.Factory.Create(this, (bool isChecked) => @ToggleColumnVisibility("ProcessId"))"></MudCheckBox>
                                <MudCheckBox Label="Integrity" Checked="@ColumnVisibility["Integrity"]" CheckedChanged="@EventCallback.Factory.Create(this, (bool isChecked) => @ToggleColumnVisibility("Integrity"))"></MudCheckBox>
                                <MudCheckBox Label="Arch" Checked="@ColumnVisibility["Arch"]" CheckedChanged="@EventCallback.Factory.Create(this, (bool isChecked) => @ToggleColumnVisibility("Arch"))"></MudCheckBox>
                                <MudCheckBox Label="Sleep" Checked="@ColumnVisibility["Sleep"]" CheckedChanged="@EventCallback.Factory.Create(this, (bool isChecked) => @ToggleColumnVisibility("Sleep"))"></MudCheckBox>
                                <MudCheckBox Label="Last Seen" Checked="@ColumnVisibility["LastSeen"]" CheckedChanged="@EventCallback.Factory.Create(this, (bool isChecked) => @ToggleColumnVisibility("LastSeen"))"></MudCheckBox>
                                <MudCheckBox Label="First Seen" Checked="@ColumnVisibility["FirstSeen"]" CheckedChanged="@EventCallback.Factory.Create(this, (bool isChecked) => @ToggleColumnVisibility("FirstSeen"))"></MudCheckBox>
                            </DialogContent>
                    <DialogActions>
                        <MudButton OnClick="@(() => OpenDialog = false)">Close</MudButton>
                    </DialogActions>
                </MudDialog>
                            <MudTable Style="width:100%;" Height="400px" Class="flex-auto" Breakpoint="Breakpoint.None" Items="@ImplantDisplayList" HorizontalScrollbar="true" Virtualize="true" FixedHeader="true" Hover="true" Dense="true" Elevation="10" Outlined="true" Striped="true" RowClassFunc="@SelectedRowClassFunc" @ref="mudTable" Filter="new Func<ExtImplant_Base,bool>(FilterFunc1)" SortLabel="Sort By">
                    <ToolBarContent>
                            <MudText Typo="Typo.h6">Implants</MudText>
                            <MudSpacer />
                            <MudToggleIconButton @bind-Toggled="@HideOfflineImplants" Color="Color.Primary" Icon="@Icons.Material.Filled.Visibility" ToggledIcon="@Icons.Material.Filled.VisibilityOff" Title="Hide Offline Implants"  ToggledTitle="Hide Offline Implants" />
                            <MudIconButton Title="Show/Hide Fields" Icon="@Icons.Material.Filled.FilterAlt" Color="Color.Primary" OnClick="@(() => OpenDialog = true)"></MudIconButton>
                            <MudTextField @bind-Value="searchString1" Placeholder="Search" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"></MudTextField>
                        </ToolBarContent>
                    <HeaderContent>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"Number")"><MudTableSortLabel SortBy="new Func<ExtImplant_Base, object>(x => x.Number)">#</MudTableSortLabel></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"")"></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"Status")"><MudTableSortLabel SortBy="new Func<ExtImplant_Base, object>(x=>x.Status)">Status</MudTableSortLabel></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"ExternalAddress")"><MudTableSortLabel SortBy="new Func<ExtImplant_Base, object>(x=>x.ExternalAddress)">External Address</MudTableSortLabel></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"ManagerName")"><MudTableSortLabel SortBy="new Func<ExtImplant_Base, object>(x=>x.Metadata.ManagerName)">Manager</MudTableSortLabel></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"ConnectionType")"><MudTableSortLabel SortBy="new Func<ExtImplant_Base, object>(x=>x.ConnectionType)">Connection Type</MudTableSortLabel></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"Address")"><MudTableSortLabel SortBy="new Func<ExtImplant_Base, object>(x=>x.Metadata.Address)">Address</MudTableSortLabel></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"Hostname")"><MudTableSortLabel SortBy="new Func<ExtImplant_Base, object>(x=>x.Metadata.Hostname)">hostname</MudTableSortLabel></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"Username")"><MudTableSortLabel SortBy="new Func<ExtImplant_Base, object>(x=>x.Metadata.Username)">username</MudTableSortLabel></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"Note")"><MudTableSortLabel SortBy="new Func<ExtImplant_Base, object>(x=>x.Note)">note</MudTableSortLabel></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"ProcessName")"><MudTableSortLabel SortBy="new Func<ExtImplant_Base, object>(x=>x.Metadata.ProcessName)">process</MudTableSortLabel></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"ProcessId")"><MudTableSortLabel SortBy="new Func<ExtImplant_Base, object>(x=>x.Metadata.ProcessId)">pid</MudTableSortLabel></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"Integrity")"><MudTableSortLabel SortBy="new Func<ExtImplant_Base, object>(x=>x.Metadata.Integrity)">Integrity</MudTableSortLabel></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"Arch")"><MudTableSortLabel SortBy="new Func<ExtImplant_Base, object>(x=>x.Metadata.Arch)">arch</MudTableSortLabel></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"Sleep")"><MudTableSortLabel SortBy="new Func<ExtImplant_Base, object>(x=>x.Metadata.Sleep)">Sleep Time</MudTableSortLabel></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"LastSeen")"><MudTableSortLabel SortBy="new Func<ExtImplant_Base, object>(x=>x.LastSeen)">lastseen</MudTableSortLabel></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"FirstSeen")"><MudTableSortLabel SortBy="new Func<ExtImplant_Base, object>(x=>x.FirstSeen)">firstseen</MudTableSortLabel></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"ImplantType")"><MudTableSortLabel SortBy="new Func<ExtImplant_Base, object>(x=>x.ImplantType)">Implant Type</MudTableSortLabel></MudTh>
                                    <MudTh Style="@setStyle(Settings.IsCheckedBox,"")">Options</MudTh>
                    </HeaderContent>
                    <RowTemplate Context="Rowcontext">
                                    <MudTd Style="@GetCellStyle("Number",Rowcontext)">@Rowcontext.Number</MudTd>
                        <MudTd>
                            <MudBadge Bordered="true" Overlap="true" Content=@ImplantInteract.SetPanelBadgeCount(Rowcontext) Color="Color.Primary">
                                            <MudIcon Size="Size.Small" Class="mb-2 ms-2" Icon=@Icons.Material.Outlined.DesktopWindows Color=@SetColor(Rowcontext.Metadata.Integrity)></MudIcon>
                            </MudBadge>
                        </MudTd>
                        <MudTd Style="@GetImplantStatus(Rowcontext)">@Rowcontext.Status</MudTd>
                                    <MudTd Style="@GetCellStyle("ExternalAddress",Rowcontext)">@Rowcontext.ExternalAddress</MudTd>
                                    <MudTd Style="@GetCellStyle("ManagerName",Rowcontext)">@Rowcontext.Metadata.ManagerName</MudTd>
                                    <MudTd Style="@GetCellStyle("ConnectionType",Rowcontext)">@Rowcontext.ConnectionType @FindManager(Rowcontext,Rowcontext.Metadata.ManagerName)</MudTd>
                                    <MudTd Style="@GetCellStyle("Address",Rowcontext)">@Rowcontext.Metadata.Address</MudTd>
                                    <MudTd Style="@GetCellStyle("Hostname",Rowcontext)">@Rowcontext.Metadata.Hostname</MudTd>
                                    <MudTd Style="@GetCellStyle("Username",Rowcontext)">@Rowcontext.Metadata.Username</MudTd>
                                <MudTd Style="@GetCellStyle("Note",Rowcontext)">@Rowcontext.Note</MudTd>
                                <MudTd Style="@GetCellStyle("ProcessName",Rowcontext)">@Rowcontext.Metadata.ProcessName</MudTd>
                                    <MudTd Style="@GetCellStyle("ProcessId",Rowcontext)">@Rowcontext.Metadata.ProcessId</MudTd>
                                    <MudTd Style="@GetCellStyle("Integrity",Rowcontext)">@Rowcontext.Metadata.Integrity</MudTd>
                                <MudTd Style="@GetCellStyle("Arch",Rowcontext)">@Rowcontext.Metadata.Arch</MudTd>
                                    <MudTd Style="@GetCellStyle("Sleep",Rowcontext)">@Rowcontext.Metadata.Sleep sec</MudTd>
                                <MudTd Style="@GetCellStyle("LastSeen",Rowcontext)">@LastSeenTimer(Rowcontext)</MudTd>
                                    <MudTd Style="@GetCellStyle("FirstSeen",Rowcontext)">@Rowcontext.FirstSeen</MudTd>
                                    <MudTd Style="@GetCellStyle("ImplantType",Rowcontext)">@Rowcontext.ImplantType</MudTd>
                        <MudTd> 
                            <MudButtonGroup Color="Color.Primary" Variant="Variant.Outlined">
                                <MudMenu Icon="@Icons.Material.Filled.ArrowDropDown">
                                    <MudMenuItem OnClick="() =>ContextMenuItems(0,Rowcontext)">Interact</MudMenuItem>
                                    <MudMenuItem OnClick="() =>ContextMenuItems(1,Rowcontext)">Note</MudMenuItem>
                                    <MudMenuItem OnClick="() =>ContextMenuItems(2,Rowcontext)">Color</MudMenuItem>
                                    <MudMenuItem OnClick="() =>ContextMenuItems(3,Rowcontext)">Exit</MudMenuItem>
                                </MudMenu>
                            </MudButtonGroup>
                        </MudTd>
                    </RowTemplate>
                </MudTable>
            </div>
            </div>

            <br>
            <ImplantCreation></ImplantCreation>
                </MudTabPanel>
                <br>
                <MudTabPanel Text="Graph View">
                    <MudPaper Height="1100px" Width="100%">
                        <ImplantGraph></ImplantGraph>
                    </MudPaper>
                </MudTabPanel>
                <br>
                <MudTabPanel Text="Compiled Implants">
                    <CompiledImplantTable></CompiledImplantTable>
                </MudTabPanel>
            </MudTabs>
        </Authorized>
    </AuthorizeView>
    <AuthorizeView Roles="Guest,Operator,TeamLead,Administrator">
        <NotAuthorized>
            <h1 class="text-center">Not Authorized</h1>
            <UnAuthorizedDialogBox></UnAuthorizedDialogBox>
        </NotAuthorized>
    </AuthorizeView>
</CascadingAuthenticationState>

@code {
    [Inject]
    private IDialogService dialogService { get; set; }
    [Inject]
    private static RestClient _restClient { get; set; }
    [Inject]
    private static IToastService toastService { get; set; }
    [Inject]
    private static NavigationManager Nav { get; set; }

    [Inject]
    public ILocalStorageService localStorage { get; set; }

    protected internal static ObservableCollection<ExtImplant_Base> ImplantList = new ObservableCollection<ExtImplant_Base>();
    //private static Dictionary<string, int> ImplantNumbers = new();
    //private static Dictionary<string, DateTime> ImplantFirstSeenDict = new();
    protected internal static List<ExtImplant_Base> ImplantDisplayList = new List<ExtImplant_Base>();
    private string ImplantTestID { get; set; }
    public Double OpacityValue { get; set; }
    private static bool Initialized = false;
    private bool success;
    private string[] errors = { };
    public MudTable<ExtImplant_Base> mudTable;
    private int selectedRowNumber = -1;
    public static string PsCmd { get; set; }
    private static Stopwatch stopwatch = new Stopwatch();
    private static bool IsCurrentLocation { get; set; }
    public static bool HideOfflineImplants { get; set; }
    public delegate Task OnStateChangeDelegate();
    public static OnStateChangeDelegate OnStateChange;
    private static DateTime? LastRefresh { get; set; } = null;
    private string searchString1 = "";
    private bool OpenDialog { get; set; } = false;
    private Dictionary<string, bool> ColumnVisibility = new Dictionary<string, bool>
    {
        { "Number", true},
        {"ImplantId",true },
        { "Status", true },
        { "ExternalAddress", true },
        { "ManagerName", true },
        { "ConnectionType", true },
        { "Address", true },
        { "Hostname", true },
        { "Username", true },
        { "Note",true},
        { "ProcessName", true },
        { "ProcessId", true },
        { "Integrity", true },
        { "Arch", true },
        { "Sleep", true },
        { "LastSeen", true },
        {"FirstSeen",true },
        {"ImplantType",true },
    };

    public static async Task SetPsCommand(string command)
    {
        PsCmd = command;
    }

    private string setStyle(bool IsDark, string fieldName)
    {
        if (!String.IsNullOrEmpty(fieldName))
        {
            if (!ColumnVisibility[fieldName])
            {
                return "display:none;";
            }
        }
        if (IsDark)
        {
            return "background:white; color:black;";
        }
        return "background:#333333; color:white;";
    }

    public static Color SetColor(string integrity)
    {
        if (integrity.Equals("high", StringComparison.CurrentCultureIgnoreCase))
        {
            return Color.Warning;
        }
        if (integrity.Equals("system", StringComparison.CurrentCultureIgnoreCase))
        {
            return Color.Error;
        }
        else if (integrity.Equals("medium", StringComparison.CurrentCultureIgnoreCase))
        {
            return Color.Info;
        }
        else if (integrity.Equals("low", StringComparison.CurrentCultureIgnoreCase))
        {
            return Color.Tertiary;
        }
        return Color.Primary;
    }

    private void ToggleColumnVisibility(string columnName)
    {
        if (ColumnVisibility.ContainsKey(columnName))
        {
            ColumnVisibility[columnName] = !ColumnVisibility[columnName];
        }
    }

    public string GetCellStyle(string columnName, ExtImplant_Base implant)
    {
        if (ColumnVisibility.ContainsKey(columnName) && ColumnVisibility[columnName])
        {
            if (implant.Status.Equals("offline",StringComparison.CurrentCultureIgnoreCase))
            {
                return "opacity:.4";
            }
            else
            {
                return "opactity:1";
            }
        }
        else
        {
            return "display:none;";
        }
    }


    void HandleClick(MouseEventArgs args)
    {
        //can handle left click inside the table
    }

    void HandleMouseUp(MouseEventArgs args)
    {
        if (args.Button == 2)
        {
            //can handle right click inside the table
            if (mudTable.SelectedItem != null)
            {
                mudTable.SelectedItem = null;
            }
        }
    }


    private string SelectedRowClassFunc(ExtImplant_Base implant, int rowNumber)
    {
        if (mudTable.SelectedItem != null && mudTable.SelectedItem.Equals(implant))
        {
            selectedRowNumber = rowNumber;
            return "selected";
        }
        else
        {
            return string.Empty;
        }
    }

    private bool FilterFunc1(ExtImplant_Base search) => FilterFunc(search, searchString1);

    private bool FilterFunc(ExtImplant_Base search, string searchString)
    {
        if (string.IsNullOrWhiteSpace(searchString))
            return true;
        //for each element in the array if it contains searchString then return true
        if (search.Metadata.Id.ToLower().Contains(searchString.ToLower()))
        {
            return true;
        }
        if (search.Metadata.Sleep.ToString().ToLower().Contains(searchString.ToLower()))
        {
            return true;
        }
        if (search.Metadata.Address.ToLower().Contains(searchString.ToLower()))
        {
            return true;
        }
        if (search.Metadata.Arch.ToString().ToLower().Contains(searchString.ToLower()))
        {
            return true;
        }
        if (search.Metadata.Hostname.ToLower().Contains(searchString.ToLower()))
        {
            return true;
        }
        if (search.Metadata.Integrity.ToLower().Contains(searchString.ToLower()))
        {
            return true;
        }
        if (search.LastSeen.ToString().ToLower().Contains(searchString.ToLower()))
        {
            return true;
        }
        if (search.Metadata.ManagerName.ToLower().Contains(searchString.ToLower()))
        {
            return true;
        }
        if (search.Metadata.Username.ToLower().Contains(searchString.ToLower()))
        {
            return true;
        }
        if (search.Metadata.ProcessId.ToString().ToLower().Contains(searchString.ToLower()))
        {
            return true;
        }
        if (search.Metadata.ProcessName.ToLower().Contains(searchString.ToLower()))
        {
            return true;
        }
        if (search.ConnectionType.ToLower().Contains(searchString.ToLower()))
        {
            return true;
        }
        if (search.ExternalAddress.ToLower().Contains(searchString.ToLower()))
        {
            return true;
        }
        if (search.Status.ToLower().Contains(searchString.ToLower()))
        {
            return true;
        }
        return false;
    }

    public async Task ContextMenuItems(int options, ExtImplant_Base implant)
    {
        switch (options)
        {
            case 0:
                //Interact
                AddImplantToInteract(implant);
                break;
            case 1:
                //note
                //cause a mud popup where the user can select to add implants from the implant table that are not yet interacted with
                var diag_options = new DialogOptions { ClassBackground = "dialog-blur-class", MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
                var dialog = dialogService.Show<ImplantNoteDiag>("Add Note to Implant", diag_options);

                var result = await dialog.Result;
                if (!result.Canceled)
                {
                    string noteString = result.Data as string;
                    //result.Data should be a string, would need to call a hub fdunction to replicate to note to all clients
                    if (!String.IsNullOrEmpty(noteString))
                    {
                        await HardHatHubClient._hub.AddNoteToImplant(implant.Metadata.Id, noteString);
                    }
                }
                break;
            case 2:
                //color
                ShowInfoToast("Color is not implemented yet");
                break;
            case 3:
                //exit
                ShowInfoToast("Exit is not implemented yet");
                break;
        }
    }

    public static void AddImplantToInteract(ExtImplant_Base implant)
    {
        if (!ImplantInteract.InteractImplants.Contains(implant))
        {
            ImplantInteract.InteractImplants.Add(implant);
        }
        //compare the eng.ProcessId@eng.Address to the values in the Interact.ImpTabTitleDic dictionary, if it matches any of the values, then add it to the dictionary but its value is ng.ProcessId@eng.Address + a number that is equal to the number of values it matched in the dictionary

        if (ImplantInteract.ImpTabTitleDic.ContainsValue(implant.Metadata.ProcessId + "@" + implant.Metadata.Address) && ImplantInteract.ImpTabTitleDic.ContainsKey(implant.Metadata.Id) == false)
        {
            int count = 0;
            foreach (string key in ImplantInteract.ImpTabTitleDic.Keys)
            {
                if (ImplantInteract.ImpTabTitleDic[key] == implant.Metadata.ProcessId + "@" + implant.Metadata.Address)
                {
                    count++;
                }
                else if (ImplantInteract.ImpTabTitleDic[key] == implant.Metadata.ProcessId + "@" + implant.Metadata.Address + "(" + count + ")")
                {
                    count++;
                }
            }
            ImplantInteract.ImpTabTitleDic.Add(implant.Metadata.Id, implant.Metadata.ProcessId + "@" + implant.Metadata.Address + "(" + count + ")");
        }
        else if (!ImplantInteract.ImpTabTitleDic.ContainsKey(implant.Metadata.Id))
        {
            ImplantInteract.ImpTabTitleDic.Add(implant.Metadata.Id, implant.Metadata.ProcessId + "@" + implant.Metadata.Address);
        }
        //check if the current window is the same implant we are trying to interact with or not
        if (ImplantInteract.interactedImplantId != null && ImplantInteract.interactedImplantId != implant.Metadata.Id)
        {
            ImplantInteract.interactedImplantId = implant.Metadata.Id;
            ImplantInteract.interactedImpIdUpdated = true;
            ImplantInteract.ImplantTaskPanels.TryAdd(implant.Metadata.Id, new InteractWindowTaskCard());
        }
        Nav.NavigateTo("/ImplantInteract");
    }

    public static async Task UpdateImplantNote(string id, string note)
    {
        foreach (var imp in ImplantList)
        {
            if (imp.Metadata.Id == id)
            {
                imp.Note = note;
            }
        }
        await Task.Delay(500);
        await OnStateChange();
    }

    public static string FindManager(ExtImplant_Base currentimp, string managerName)
    {
        if (currentimp.ConnectionType.Equals("http", StringComparison.CurrentCultureIgnoreCase) || currentimp.ConnectionType.Equals("https", StringComparison.CurrentCultureIgnoreCase))
        {
            return "";
        }
        foreach (var man in Managers.managersList)
        {
            if (man.Name == managerName)
            {
                return man.connectionMode.ToString();
            }
        }
        return "";
    }

    public static async Task CreateImplant(ExtImplantCreateRequest_Base formData, List<string> selectedImpCommandList, List<string> selectedImpModuleList)
    {
        try
        {
            string resource = "/implants";
            var createObject = new ExtImplantCreateRequest_Base
                {
                    managerName = formData.managerName,
                    ConnectionAttempts = formData.ConnectionAttempts,
                    Sleep = formData.Sleep,
                    complieType = formData.complieType,
                    WorkingHours = formData.WorkingHours,
                    SleepType = formData.SleepType,
                    KillDateTime = formData.selectedKillDate is null ? null : (DateTime)(formData.selectedKillDate.Value.Date + formData.selectedKillTime),
                    IncludedCommands = selectedImpCommandList.ToList(),
                    IncludedModules = selectedImpModuleList.ToList(),
                    ChunkSize = formData.ChunkSize ?? 0,
                    IsChunkEnabled = formData.IsChunkEnabled ?? false,
                    implantType = formData.implantType,
                    implantOsType = formData.implantOsType,
                };

            var request = new RestRequest(resource, Method.Post);
            request.AddJsonBody(createObject);
            ShowInfoToast("Sending Request To Create Implant");
            await OnStateChange();
            // request.OnBeforeDeserialization = resp =>
            // {
            //     Console.WriteLine(resp.Content);
            // };
            var requestResponse = await _restClient.PostAsync<string>(request);
            if (requestResponse != null)
            {
                ShowSuccessToast(requestResponse);
            }
            //reset the form data object
            formData = new ExtImplantCreateRequest_Base();
            await OnStateChange();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            Console.WriteLine(ex.StackTrace);
        }

    }

    public static async Task GetAllImplants()
    {
        string resource = "/implants";
        var request = new RestRequest(resource, Method.Get);
        try
        {
            var requestResponse = await _restClient.GetAsync<List<ExtImplant_Base>>(request);
            if (requestResponse != null)
            {
                foreach (ExtImplant_Base implantresponse in requestResponse)
                {
                    var implant = ImplantList.FirstOrDefault(x => x?.Metadata.Id == implantresponse.Metadata.Id, defaultValue: null);
                    if (implant != null)
                    {
                        implant.LastSeen = implantresponse.LastSeen;
                        implant.Metadata.Sleep = implantresponse.Metadata.Sleep;
                    }
                    else
                    {
                        ImplantList.Add(implantresponse);
                    }
                }
            }
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex.Message);    

        }
    }

    public static async Task CheckInImplant(ExtImplant_Base implant)
    {
        //see if the implant is already in the list
        var Currentimplant = ImplantList.FirstOrDefault(x => x?.Metadata.Id == implant.Metadata.Id,defaultValue: null);
        if (Currentimplant != null)
        {
            // update the object with the new values
            Currentimplant.LastSeen = implant.LastSeen;
            Currentimplant.Metadata.Sleep = implant.Metadata.Sleep;
        }
        else
        {
            ImplantList.Add(implant);
        }
    }


    public static string GetImplantStatus(ExtImplant_Base implant)
    {
        // if implant LastSeen is in the past then Status is offline
        // add 5 seconds to the LastSeen to make sure the implant is still online
        int sleepTime = implant.Metadata.Sleep;
        //makes it so the ui wont auto timeout implants at sleep 0 unless they dont check in for 4-5 seconds
        if (sleepTime == 0)
        {
            sleepTime = 2;
        }
        if (implant.LastSeen.AddSeconds(sleepTime * 3) < DateTime.UtcNow)
        {
            implant.Status = "Offline";
            return "opacity:.4";
        }
        else
        {
            implant.Status = "Active";
            return "opactity:1";
        }
    }

    public static string LastSeenTimer(ExtImplant_Base implant)
    {
        string output = "";
        //based on lastSeen time use a timer and return the time since last seen in a string, print ms if less than 1 second print seconds if less than 1 minute print minutes if less than 1 hour print hours if less than 1 day print , only print the whole number
        var timeSinceLastSeen = DateTime.UtcNow - implant.LastSeen;
        //dont let the timeSinceLastSeen be negative
        if (timeSinceLastSeen < TimeSpan.Zero)
        {
            timeSinceLastSeen = timeSinceLastSeen.Negate();
        }

        if (timeSinceLastSeen.TotalMilliseconds < 1000)
        {
            output = implant.LastSeenTimer = $"{timeSinceLastSeen.Milliseconds} ms";
        }
        else if (timeSinceLastSeen.TotalSeconds < 60)
        {
            output = implant.LastSeenTimer = $"{timeSinceLastSeen.Seconds} sec";
        }
        else if (timeSinceLastSeen.TotalMinutes < 60)
        {
            output = implant.LastSeenTimer = $"{timeSinceLastSeen.Minutes} min";
        }
        else if (timeSinceLastSeen.TotalHours < 24)
        {
            output = implant.LastSeenTimer = $"{timeSinceLastSeen.Hours} hours";
        }
        else if (timeSinceLastSeen.TotalDays < 1)
        {
            output = implant.LastSeenTimer = $"{timeSinceLastSeen.Days} days";
        }
        else
        {
            output = implant.LastSeenTimer = $"{timeSinceLastSeen.Days} days";
        }
        OnStateChange();
        return output;
    }

    public static void ShowSuccessToast(string successMessage)
    {
        toastService.ShowSuccess(successMessage);
    }
    public static void ShowErrorToast(string errorMessage)
    {
        toastService.ShowError(errorMessage);
    }

    public static void ShowInfoToast(string infoMessage)
    {
        toastService.ShowInfo(infoMessage);
    }

    public static void ShowWarningToast(string warningmessage)
    {
        toastService.ShowWarning(warningmessage);
    }


    public async Task ImplementOnStateChangeEvent()
    {
        if (LastRefresh == null)
        {
            LastRefresh = DateTime.Now;
            InvokeAsync(StateHasChanged);
        }
        else
        {
            // if more then 500 ms has passed since the last refresh then refresh the page
            if (DateTime.Now.Subtract(LastRefresh.Value).TotalMilliseconds > 500)
            {
                LastRefresh = DateTime.Now;
                await Task.Delay(100);
                await InvokeAsync(StateHasChanged);
            }
        }
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            _restClient = restClientDefault;
            string jwtToken = await localStorage.GetItemAsync<string>("bearerToken");
            RestClientOptions options = new RestClientOptions();
            options.BaseUrl = _restClient.Options.BaseUrl;
            options.RemoteCertificateValidationCallback = _restClient.Options.RemoteCertificateValidationCallback;
            options.Authenticator = new JwtAuthenticator(jwtToken);
            _restClient = new RestClient(options);
            await Implants.GetAllImplants();
        }
    }

    protected override async Task OnInitializedAsync()
    {
        OnStateChange = ImplementOnStateChangeEvent;
        toastService = toastDefault;
        //nav here is used by the options menu to start interaction so dont remove
        Nav = navigationManagerDefault;

        if (stopwatch.IsRunning == false)
        {
            stopwatch.Start();
            Task.Run(() =>
            {
                while (true)
                {
                    if (stopwatch.ElapsedMilliseconds > 500)
                    {
                        OnStateChange();
                        stopwatch.Restart();
                    }
                    Thread.Sleep(100);
                }
            });
        }
    }


}
